// generator用大白话来说就是一个能够多次返回的函数
//Generator函数是ES6提供的一种异步编程解决方案。Generator函数是一个状态机, 使用yield表达式定义了多个内部状态。
// 同时还是一个迭代器对象(Iterator)的生成函数，返回的迭代器对象利用next方法可以依次遍历Generator函数内部的每一个状态。

//执行机制:调用Generator函数后 函数并不执行 而是返回一个迭代器当该迭代器第一次调用next方法时，函数从头开始执行 ， 
// 内部指针从函数头部指向第一个yield语句，函数执行到该yield语句之后自动暂停，
// yield后面表达式的值会作为next方法的返回值中的value值。
// 当迭代器再次调用next方法时才会从上次停止的地方 (yield ［表达式］处的后面)开始继续执行， 
// 直到执行完下一句yield语句，或return语句为止

function *generatorF(){
    yield 1;
    yield 2;
    yield 3;
}

let generator=generatorF();

console.log(generator.next().value);
console.log(generator.next().value);
console.log(generator.next().value);


//比如一个斐波那契数列
function fib(max) {
    var
        a = 0,
        b = 1,
        arr = [0, 1];
    while (arr.length < max) {
        [a, b] = [b, a + b];
        arr.push(b);
    }
    return arr;
}
fib(5); // [0, 1, 1, 2, 3] 缺点是只能返回一次，所以必须返回一个Array,但是换成generator,就可以一次返回一个数，不断的返回多次

function *fib1(max){
    var
        a=0,
        b=1,
        n=0;
    while(n<max){
        yield a;
        [a,b]=[b,a+b];
        n++;

    }
    return;
}
fib(5);//fib {[[GeneratorStatus]]: "suspended", [[GeneratorReceiver]]: Window}
//fib(5)仅仅创建了一个generator对象，还没有去执行它
//调用generator对象有两个方法，一是不断地调用generator对象的next()方法，
var f = fib(5);
f.next(); // {value: 0, done: false}
f.next(); // {value: 1, done: false}
f.next(); // {value: 1, done: false}
f.next(); // {value: 2, done: false}
f.next(); // {value: 3, done: false}
f.next(); // {value: undefined, done: true}
//每次返回的value就是yield的值，done表示这个generator是否执行结束，如果done为true

//第二个方法是直接用for...of循环迭代generator对象，此时不需要是否执行完毕了
for(var x of fib(10)){
    console.log(x);
    
}

//generator和普通函数相比 特点是它是可以记住执行状态的函数  用一个对象来保存状态得如下写法：
var fib = {
    a: 0,
    b: 1,
    n: 0,
    max: 5,
    next: function () {
        var
            r = this.a,
            t = this.a + this.b;
        this.a = this.b;
        this.b = t;
        if (this.n < this.max) {
            this.n ++;
            return r;
        } else {
            return undefined;
        }
    }
};


//